﻿using IncomeOutcome.Model;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IncomeOutcome.ViewModel
{
    public class ItemValueViewModel : INotifyPropertyChanged
    {
        // LINQ to SQL data context for the local database.
        private AppDataContext m_AppDataContext;

        private ObservableCollection<ItemValue> m_ItemValues;
        public ObservableCollection<ItemValue> ItemValues
        {
            get { return m_ItemValues; }
            set
            {
                m_ItemValues = value;
                NotifyPropertyChanged("ItemValues");
            }
        }

        private Item m_Item;
        public Item Item
        {
            get { return m_Item; }
            set
            {
                m_Item = value;
                NotifyPropertyChanged("Item");
            }
        }

        #region Properties
        // ItemId.
        private int m_ItemId;
        public int ItemId
        {
            get { return m_ItemId; }
            set { m_ItemId = value; NotifyPropertyChanged("ItemId"); }
        }
        // ItemIndex.
        private int m_ItemIndex = -1;
        public int ItemIndex
        {
            get { return m_ItemIndex; }
            set { m_ItemIndex = value; NotifyPropertyChanged("ItemIndex"); }
        }
        //// PreviousItemId.
        //private int m_PreviousItemId;
        //public int PreviousItemId
        //{
        //    get { return m_PreviousItemId; }
        //    set { m_PreviousItemId = value; NotifyPropertyChanged("PreviousItemId"); }
        //}
        //// NextItemId.
        //private int m_NextItemId;
        //public int NextItemId
        //{
        //    get { return m_NextItemId; }
        //    set { m_NextItemId = value; NotifyPropertyChanged("NextItemId"); }
        //}
        // IsSign.
        private string m_IsSign = "+";
        public string IsSign
        {
            get { return m_IsSign; }
            set { m_IsSign = value; NotifyPropertyChanged("IsSign"); }
        }
        // NumberInput.
        private double m_NumberInput;
        public double NumberInput
        {
            get { return m_NumberInput; }
            set { m_NumberInput = value; NotifyPropertyChanged("NumberInput"); }
        }
        // NumberInputString.
        private string m_NumberInputString = "0";
        public string NumberInputString
        {
            get { return m_NumberInputString; }
            set { m_NumberInputString = value; NotifyPropertyChanged("NumberInputString"); }
        }
        // ImagePath.
        private string m_ImagePath;
        public string ImagePath
        {
            get { return m_ImagePath; }
            set { m_ImagePath = value; NotifyPropertyChanged("ImagePath"); }
        }
        // ItemCount.
        private int m_ItemCount;
        public int ItemCount
        {
            get { return m_ItemCount; }
            set { m_ItemCount = value; NotifyPropertyChanged("ItemCount"); }
        }
        // ItemValueCount.
        private int m_ItemValueCount;
        public int ItemValueCount
        {
            get { return m_ItemValueCount; }
            set { m_ItemValueCount = value; NotifyPropertyChanged("ItemValueCount"); }
        }
        // ItemValueTotal.
        private double m_ItemValueTotal;
        public double ItemValueTotal
        {
            get { return m_ItemValueTotal; }
            set { m_ItemValueTotal = value; NotifyPropertyChanged("ItemValueTotal"); }
        }
        #endregion Properties End

        // Class constructor, create the data context object.
        public ItemValueViewModel(string pConnectionString)
        {
            m_AppDataContext = new AppDataContext(pConnectionString);
            // Get number of items.
            ItemCount = m_AppDataContext.Items.Count();
            //GetFirstItem();
            GetLastItem();
        }

        // Write changes in the data context to the database.
        public void SaveChangesToDB()
        {
            m_AppDataContext.SubmitChanges();
        }

        public bool AddItem(string pName)
        {
            Item oItem = new Model.Item();
            oItem.ItemName = pName;
            oItem.ImagePath = string.Empty;
            if (Item == null)
            {
                oItem.PreviousItemId = oItem.NextItemId = -1;
            }
            else
            {
                int iNextItemId = Item.NextItemId;
                oItem.PreviousItemId = ItemId;
                oItem.NextItemId = iNextItemId;
            }
            // Add a item to the data context.
            m_AppDataContext.Items.InsertOnSubmit(oItem);
            // Save changes to the database.
            SaveChangesToDB();
            if (Item != null)
            {
                Item.NextItemId = oItem.ItemId;
                if (oItem.NextItemId != -1)
                {
                    Item = m_AppDataContext.Items.Where(p => p.ItemId == oItem.NextItemId).FirstOrDefault();
                    Item.PreviousItemId = oItem.ItemId;
                }
                SaveChangesToDB();
            }

            ItemId = oItem.ItemId;
            ItemCount++;
            ItemIndex++;
            ItemValueCount = 0;
            ItemValueTotal = 0;
            ImagePath = string.Empty;
            Item = oItem;
            if (ItemValues == null)
            {
                ItemValues = new ObservableCollection<ItemValue>();
            }
            else
            {
                ItemValues.Clear();
            }
            return true;
        }
        // Remove item.
        public bool RemoveItem()
        {
            Item oItem = null;
            if (Item.PreviousItemId != -1)
            {
                oItem = m_AppDataContext.Items.Where(p => p.ItemId == Item.PreviousItemId).FirstOrDefault();
                oItem.NextItemId = Item.NextItemId;
            }
            if (Item.NextItemId != -1)
            {
                oItem = m_AppDataContext.Items.Where(p => p.ItemId == Item.NextItemId).FirstOrDefault();
                oItem.PreviousItemId = Item.PreviousItemId;
            }
            else
                ItemIndex--;

            // Delete ItemValues and Item in database.
            m_AppDataContext.ItemValues.DeleteAllOnSubmit(Item.ItemValues);
            Item.ItemValues.Clear();
            if (ItemValues != null)
            {
                ItemValues.Clear();
            }
            // Delete a item in the database.
            m_AppDataContext.Items.DeleteOnSubmit(Item);
            // Save changes to the database.
            SaveChangesToDB();
            if (oItem != null)
            {
                ItemCount--;
                Item = oItem;
                ImagePath = Item.ImagePath;
                ItemId = Item.ItemId;
                ItemValues = new ObservableCollection<ItemValue>(Item.ItemValues);
                // Get number of count and total value.
                ItemValueCount = m_Item.ItemValues.Count();
                ItemValueTotal = m_Item.ItemValues.Sum(p => p.NumberValue);
            }
            else
            {
                ItemCount = 0;
                ItemIndex = -1;
                ImagePath = string.Empty;
                Item = null;
                AddItem("ItemName");
            }
            return true;
        }
        // First item.
        public bool FirstItem()
        {
            if (Item.PreviousItemId != -1)
            {
                //Item.ItemId = Item.PreviousItemId;
                Item = m_AppDataContext.Items.Where(p => p.PreviousItemId == -1).FirstOrDefault();
                ItemId = Item.ItemId;
                ImagePath = Item.ImagePath;
                if (ItemValues != null)
                {
                    ItemValues.Clear();
                }
                ItemValues = new ObservableCollection<ItemValue>(Item.ItemValues);
                // Get number of count and total value.
                ItemValueCount = m_Item.ItemValues.Count();
                ItemValueTotal = m_Item.ItemValues.Sum(p => p.NumberValue);
                ItemIndex = 0;
                return true;
            }
            return false;
        }
        // Previous item.
        public bool PreviousItem()
        {
            if (Item.PreviousItemId != -1)
            {
                //Item.ItemId = Item.PreviousItemId;
                Item = m_AppDataContext.Items.Where(p => p.ItemId == Item.PreviousItemId).FirstOrDefault();
                ItemId = Item.ItemId;
                ImagePath = Item.ImagePath;
                if (ItemValues != null)
                {
                    ItemValues.Clear();
                }
                ItemValues = new ObservableCollection<ItemValue>(Item.ItemValues);
                // Get number of count and total value.
                ItemValueCount = m_Item.ItemValues.Count();
                ItemValueTotal = m_Item.ItemValues.Sum(p => p.NumberValue);
                ItemIndex--;

                return true;
            }
            return false;
        }
        // Next item.
        public bool NextItem()
        {
            if (Item.NextItemId != -1)
            {
                //Item.ItemId = Item.NextItemId;
                Item = m_AppDataContext.Items.Where(p => p.ItemId == Item.NextItemId).FirstOrDefault();
                ItemId = Item.ItemId;
                ImagePath = Item.ImagePath;
                if (ItemValues != null)
                {
                    ItemValues.Clear();
                }
                ItemValues = new ObservableCollection<ItemValue>(Item.ItemValues);
                // Get number of count and total value.
                ItemValueCount = m_Item.ItemValues.Count();
                ItemValueTotal = m_Item.ItemValues.Sum(p => p.NumberValue);
                ItemIndex++;

                return true;
            }
            return false;
        }
        // Last item.
        public bool LastItem()
        {
            if (Item.NextItemId != -1)
            {
                //Item.ItemId = Item.NextItemId;
                Item = m_AppDataContext.Items.Where(p => p.NextItemId == -1).FirstOrDefault();
                ItemId = Item.ItemId;
                ImagePath = Item.ImagePath;
                if (ItemValues != null)
                {
                    ItemValues.Clear();
                }
                ItemValues = new ObservableCollection<ItemValue>(Item.ItemValues);
                // Get number of count and total value.
                ItemValueCount = m_Item.ItemValues.Count();
                ItemValueTotal = m_Item.ItemValues.Sum(p => p.NumberValue);
                ItemIndex = ItemCount - 1;

                return true;
            }
            return false;
        }
        // Save Image path.
        public void SaveImagePath()
        {
            Item oItem = m_AppDataContext.Items.Where(p => p.ItemId == Item.ItemId).FirstOrDefault();
            oItem.ImagePath = ImagePath;
            SaveChangesToDB();
        }
        // Get number of items.
        public int GetCountItem()
        {
            return m_AppDataContext.Items.Count();
        }
        // Get First Item.
        public void GetFirstItem()
        {
            Item oItem = m_AppDataContext.Items.Where(p => p.PreviousItemId == -1).FirstOrDefault();
            if (oItem == null)
            {
                AddItem("ItemName");
            }
            else
            {
                ItemId = oItem.ItemId;
                Item = oItem;
                if (ItemValues != null)
                    ItemValues.Clear();
                ItemValues = new ObservableCollection<ItemValue>(oItem.ItemValues);
                ItemValueCount = oItem.ItemValues.Count();
                ItemValueTotal = oItem.ItemValues.Sum(p => p.NumberValue);
                ImagePath = oItem.ImagePath;
            }
            ItemIndex = 0;
        }
        // Get Last Item.
        public void GetLastItem()
        {
            Item oItem = m_AppDataContext.Items.Where(p => p.NextItemId == -1).FirstOrDefault();
            if (oItem == null)
            {
                AddItem("ItemName");
            }
            else
            {
                ItemId = oItem.ItemId;
                Item = oItem;
                if (ItemValues != null)
                    ItemValues.Clear();
                ItemValues = new ObservableCollection<ItemValue>(oItem.ItemValues);
                ItemValueCount = oItem.ItemValues.Count();
                ItemValueTotal = oItem.ItemValues.Sum(p => p.NumberValue);
                ImagePath = oItem.ImagePath;
            }
            ItemIndex = ItemCount - 1;
        }

        // Add a to-do item to the database and collections.
        public void AddItemValue()
        {
            ItemValue oItemValue = new ItemValue();
            NumberInput = double.Parse(NumberInputString);
            if (IsSign == "-")
                NumberInput *= -1;
            oItemValue.NumberValue = NumberInput;
            oItemValue.ValueOrder = ItemValues.Count() + 1;
            oItemValue.Item = Item;
            // Add a item value to the database.
            m_AppDataContext.ItemValues.InsertOnSubmit(oItemValue);

            // Save changes to the database.
            SaveChangesToDB();

            // Add a item value to the data members (on this).
            Item.ItemValues.Add(oItemValue);
            ItemValues.Add(oItemValue);
            ItemValueCount++;
            ItemValueTotal += NumberInput;
            NumberInput = 0;
            NumberInputString = "0";
        }

        // Remove a item value from the database and collections.
        public void DeleteItemValue(ItemValue pItemValue)
        {
            // Remove the to-do item from the data context.
            m_AppDataContext.ItemValues.DeleteOnSubmit(pItemValue);

            // Save changes to the database.
            m_AppDataContext.SubmitChanges();

            // Remove the item value from the data members (on this).
            ItemValues.Remove(pItemValue);
            Item.ItemValues.Remove(pItemValue);
            ItemValueCount--;
            ItemValueTotal -= pItemValue.NumberValue;
        }

        public void ResetItemValues()
        {
            try
            {
                m_AppDataContext.ItemValues.DeleteAllOnSubmit(Item.ItemValues);
                Item.ItemValues.Clear();

                SaveChangesToDB();

                ItemValues.Clear();
                NotifyPropertyChanged("ItemValues");
                ItemValueTotal = ItemValueCount = 0;
            }
            catch (Exception ex)
            {
            }
        }

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;
        // Used to notify Silverlight that a property has changed.
        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}
